﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Data.Common;
using System.Data.SqlClient;
using Apq.DB;

namespace Apq.Windows.UserControls
{
	public partial class MsSqlConnector : System.Windows.Forms.UserControl
	{
		public MsSqlConnector()
		{
			InitializeComponent();

			cbiNameHelper = new Forms.ComboBoxItemsHelper(cbName.Items, this);
		}

		/// <summary>
		/// 提供UI线程锁
		/// </summary>
		public object LockUI = new object();

		/// <summary>
		/// 设置界面语言
		/// </summary>
		public void SetUILang(Apq.UILang.UILang UILang)
		{
			this.Text = UILang["连接到MsSql数据库"];

			lblName.Text = UILang["名称："];
			lblServer.Text = UILang["服务器："];
			lblUserId.Text = UILang["用户名："];
			lblPwd.Text = UILang["密码："];
			lblPort.Text = UILang["端口："];
			lblDBName.Text = UILang["数据库列表："];

			cbSavePwd.Text = UILang["保存密码"];

			btnSave.Text = UILang["保存(&S)"];
			btnRefresh.Text = UILang["刷新(&F)"];
			btnTest.Text = UILang["测试连接(&T)"];
		}

		private string _ConnectionFolder = string.Empty;
		/// <summary>
		/// 存放连接文件夹的路径
		/// </summary>
		private string ConnectionFolder
		{
			get
			{
				if (string.IsNullOrWhiteSpace(_ConnectionFolder))
				{
					ConnectionFolder = Path.GetDirectoryName(Apq.GlobalObject.TheProcess.MainModule.FileName) + @"\MsSqlConnect";
				}
				if (!Directory.Exists(_ConnectionFolder))
				{
					Directory.CreateDirectory(_ConnectionFolder);
				}
				return _ConnectionFolder;
			}
			set
			{
				_ConnectionFolder = value;
				cbiNameHelper.fsw_Set(ConnectionFolder, "*.xml");
			}
		}

		private Forms.ComboBoxItemsHelper cbiNameHelper = null;

		/// <summary>
		/// UI默认值(由用户输入部分)
		/// </summary>
		public void SetUIDefault()
		{
			lock (LockUI)
			{
				Apq.GlobalObject.EventSuspend.AddUnique(new Apq.CSMember(txtServer, "TextUpdate"));
				Apq.GlobalObject.EventSuspend.AddUnique(new Apq.CSMember(cbDBName, "TextUpdate"));

				txtServer.Text = "localhost";
				txtUserId.Text = "root";
				txtPwd.Text = string.Empty;
				txtPort.Text = "3306";

				cbDBName.Items.Clear();
				cbDBName.Text = string.Empty;

				Apq.GlobalObject.EventSuspend.Remove(new Apq.CSMember(cbDBName, "TextUpdate"));
				Apq.GlobalObject.EventSuspend.Remove(new Apq.CSMember(txtServer, "TextUpdate"));
			}
		}

		/// <summary>
		/// 启用“保存”按钮可用状态
		/// </summary>
		private void btnSave_Enable()
		{
			if (!btnSave.Enabled && !string.IsNullOrWhiteSpace(cbName.Text))
			{
				btnSave.Enabled = true;
			}
		}

		/// <summary>
		/// UI可用性
		/// </summary>
		public void UIEnable(bool Enable)
		{
			cbName.Enabled = Enable;
			txtServer.Enabled = Enable;
			txtUserId.Enabled = Enable;
			txtPwd.Enabled = Enable;
			txtPort.Enabled = Enable;
			cbDBName.Enabled = Enable;

			cbSavePwd.Enabled = Enable;

			btnTest.Enabled = Enable;
		}

		/// <summary>
		/// 从界面创建MsSql连接
		/// </summary>
		public SqlConnection CreateMsSqlConnection(bool ForTest = false)
		{
			lock (LockUI)
			{
				DbConnectionHelper.Close(_MsSqlConnection);
				_MsSqlConnection.ConnectionString = Apq.DB.Common.GetConnectionString(DBProduct.MsSql,
					txtServer.Text,
					Apq.Convert.ChangeType<int>(txtPort.Text, 1433),
					txtUserId.Text,
					txtPwd.Text,
					ForTest || string.IsNullOrWhiteSpace(cbDBName.Text) ? "master" : cbDBName.Text
				);
			}

			return _MsSqlConnection;
		}

		private void MsSqlConnector_Load(object sender, EventArgs e)
		{
			cbiNameHelper.Items_Reset(ConnectionFolder);
			cbiNameHelper.fsw.Start();

			if (AutoLoadProject)
			{
				string strMsSqlName = Apq.Win.GlobalObject.XmlConfigChain[this.GetType(), "MsSqlConnectionFileName"] ?? string.Empty;
				cbName.SelectedIndex = cbName.Items.IndexOf(strMsSqlName);
			}
		}

		/// <summary>
		/// 打开连接文件
		/// </summary>
		private void cbName_SelectedIndexChanged(object sender, EventArgs e)
		{
			if (!Apq.GlobalObject.EventSuspend.Contains(new Apq.CSMember(cbName, "SelectedIndexChanged")))
			{
				try
				{
					Apq.Win.GlobalObject.XmlConfigChain[this.GetType(), "MsSqlConnectionFileName"] = cbName.Text;
					Apq.Win.GlobalObject.XmlConfigChain.Save();

					SetUIDefault();

					//打开连接文件解密密码并对界面赋值
					Apq.Windows.Forms.DBConnector_XSD xsd = new Apq.Windows.Forms.DBConnector_XSD();
					xsd.MsSql.ReadXml(ConnectionFolder + @"\" + cbName.Text + ".xml");
					if (xsd.MsSql.Rows.Count > 0)
					{
						Apq.Windows.Forms.DBConnector_XSD.MsSqlRow dr = xsd.MsSql.Rows[0] as Apq.Windows.Forms.DBConnector_XSD.MsSqlRow;
						dr.PwdD = Apq.Security.Cryptography.DESHelper.DecryptString(Apq.Convert.ChangeType<string>(dr["PwdC"]),
							Apq.Win.GlobalObject.XmlAsmConfig["Apq.Win.GlobalObject", "DESKey"],
							Apq.Win.GlobalObject.XmlAsmConfig["Apq.Win.GlobalObject", "DESIV"]
						);

						Apq.GlobalObject.EventSuspend.AddUnique(new Apq.CSMember(txtServer, "TextUpdate"));
						Apq.GlobalObject.EventSuspend.AddUnique(new Apq.CSMember(cbDBName, "TextUpdate"));
						Apq.GlobalObject.EventSuspend.AddUnique(new Apq.CSMember(cbDBName, "SelectedIndexChanged"));
						lock (LockUI)
						{
							txtServer.Text = dr.Server;
							txtUserId.Text = dr.Uid;
							txtPwd.Text = dr.PwdD;
							txtPort.Text = dr.Port;
							if (!dr.IsDBNameNull())
							{
								cbDBName.Text = dr.DBName;
							}
						}
						Apq.GlobalObject.EventSuspend.Remove(new Apq.CSMember(cbDBName, "SelectedIndexChanged"));
						Apq.GlobalObject.EventSuspend.Remove(new Apq.CSMember(cbDBName, "TextUpdate"));
						Apq.GlobalObject.EventSuspend.Remove(new Apq.CSMember(txtServer, "TextUpdate"));

						//btnSave.Enabled = false;
					}
				}
				catch (System.Exception ex)
				{
					MessageBox.Show(this, ex.Message);
				}
			}
		}

		/// <summary>
		/// 保存界面到文件
		/// </summary>
		private void btnSave_Click(object sender, EventArgs e)
		{
			if (string.IsNullOrWhiteSpace(cbName.Text))
			{
				return;
			}

			try
			{
				Apq.Win.GlobalObject.XmlConfigChain[this.GetType(), "MsSqlConnectionFileName"] = cbName.Text;
				Apq.Win.GlobalObject.XmlConfigChain.Save();

				//获取界面值，加密密码后生成连接文件，覆盖保存
				Apq.Windows.Forms.DBConnector_XSD xsd = new Apq.Windows.Forms.DBConnector_XSD();
				DataRow dr = xsd.MsSql.NewRow();
				xsd.MsSql.Rows.Add(dr);
				lock (LockUI)
				{
					dr["Server"] = txtServer.Text;
					dr["Port"] = txtPort.Text;
					dr["Uid"] = txtUserId.Text;
					dr["PwdD"] = txtPwd.Text;
					if (!string.IsNullOrWhiteSpace(cbDBName.Text))
					{
						dr["DBName"] = cbDBName.Text;
					}
					if (cbSavePwd.Checked)
					{
						dr["PwdC"] = Apq.Security.Cryptography.DESHelper.EncryptString(txtPwd.Text,
							Apq.Win.GlobalObject.XmlAsmConfig["Apq.Win.GlobalObject", "DESKey"],
							Apq.Win.GlobalObject.XmlAsmConfig["Apq.Win.GlobalObject", "DESIV"]
						);
					}
				}

				xsd.MsSql.Columns.Remove("PwdD");
				if (!cbSavePwd.Checked)
				{
					xsd.MsSql.Columns.Remove("PwdC");
				}

				xsd.MsSql.WriteXml(ConnectionFolder + @"\" + cbName.Text + ".xml", XmlWriteMode.IgnoreSchema);
				btnSave.Enabled = false;
			}
			catch (System.Exception ex)
			{
				MessageBox.Show(this, ex.Message);
			}
		}

		/// <summary>
		/// 刷新
		/// </summary>
		private void btnRefresh_Click(object sender, EventArgs e)
		{
			try
			{
				Cursor = Cursors.WaitCursor;
				UIEnable(false);
				cbDBName.Items.Clear();

				// 创建连接
				CreateMsSqlConnection(true);

				// 获取数据库列表
				DataSet ds = new DataSet();
				DbConnectionHelper dch = new DbConnectionHelper(_MsSqlConnection);
				DbDataAdapter dda = dch.CreateAdapter(@"SELECT name FROM sys.databases");
				dda.Fill(ds);

				// 填充到下拉框选项
				foreach (DataRow dr in ds.Tables[0].Rows)
				{
					cbDBName.Items.Add(dr[0]);
				}
			}
			catch (System.Exception ex)
			{
				MessageBox.Show(this, ex.Message);
			}
			finally
			{
				DbConnectionHelper.Close(_MsSqlConnection);
				UIEnable(true);
				Cursor = Cursors.Default;
			}
		}

		/// <summary>
		/// 测试
		/// </summary>
		private void btnTest_Click(object sender, EventArgs e)
		{
			try
			{
				Cursor = Cursors.WaitCursor;
				UIEnable(false);

				CreateMsSqlConnection();
				_MsSqlConnection.Open();
				DbConnectionHelper.Close(_MsSqlConnection);
				MessageBox.Show(this, Apq.GlobalObject.UILang["连接成功！"]);
			}
			catch (System.Exception ex)
			{
				MessageBox.Show(this, ex.Message);
			}
			finally
			{
				DbConnectionHelper.Close(_MsSqlConnection);
				UIEnable(true);
				Cursor = Cursors.Default;
			}
		}

		#region 从界面值输入时启用保存按钮
		private void cbName_TextUpdate(object sender, EventArgs e)
		{
			btnSave_Enable();
		}

		private void txtServer_TextChanged(object sender, EventArgs e)
		{
			if (!Apq.GlobalObject.EventSuspend.Contains(new Apq.CSMember(txtServer, "TextUpdate")))
			{
				CalcProjectName();
			}
			btnSave_Enable();
		}

		private void txtUserId_TextChanged(object sender, EventArgs e)
		{
			btnSave_Enable();
		}

		private void txtPwd_TextChanged(object sender, EventArgs e)
		{
			btnSave_Enable();
		}

		private void txtPort_TextChanged(object sender, EventArgs e)
		{
			btnSave_Enable();
		}

		private void cbDBName_SelectedIndexChanged(object sender, EventArgs e)
		{
			if (!Apq.GlobalObject.EventSuspend.Contains(new Apq.CSMember(cbDBName, "SelectedIndexChanged")))
			{
				CalcProjectName();
			}
			btnSave_Enable();
		}

		private void cbDBName_TextUpdate(object sender, EventArgs e)
		{
			if (!Apq.GlobalObject.EventSuspend.Contains(new Apq.CSMember(cbDBName, "TextUpdate")))
			{
				CalcProjectName();
			}
			btnSave_Enable();
		}

		private void cbSavePwd_CheckedChanged(object sender, EventArgs e)
		{
			btnSave_Enable();
		}

		/// <summary>
		/// 计算连接方案名
		/// </summary>
		public void CalcProjectName()
		{
			Apq.GlobalObject.EventSuspend.AddUnique(new Apq.CSMember(cbName, "TextUpdate"));
			Apq.GlobalObject.EventSuspend.AddUnique(new Apq.CSMember(cbName, "SelectedIndexChanged"));
			cbName.Text = txtServer.Text;
			if (!string.IsNullOrWhiteSpace(cbDBName.Text))
			{
				cbName.Text += "-" + cbDBName.Text;
			}
			Apq.GlobalObject.EventSuspend.Remove(new Apq.CSMember(cbName, "SelectedIndexChanged"));
			Apq.GlobalObject.EventSuspend.Remove(new Apq.CSMember(cbName, "TextUpdate"));
		}
		#endregion

		private bool _AutoLoadProject = true;
		/// <summary>
		/// 获取或设置是否自动加载连接方案文件(用于加载控件时)
		/// </summary>
		[Editor()]
		public bool AutoLoadProject
		{
			get { return _AutoLoadProject; }
			set { _AutoLoadProject = value; }
		}
	}
}
